home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / mac / DirectX SDK / DXSDK / include / dmoimpl.h < prev    next >
C/C++ Source or Header  |  2001-10-08  |  22KB  |  646 lines

  1. //------------------------------------------------------------------------------
  2. // File: DMOImpl.h
  3. //
  4. // Desc: Classes to implement a DMO.
  5. //
  6. // Copyright (c) 2000-2001, Microsoft Corporation.  All rights reserved.
  7. //------------------------------------------------------------------------------
  8.  
  9.  
  10. #ifndef _dmoimpl_h_
  11. #define _dmoimpl_h_
  12.  
  13. #ifdef _DEBUG
  14. #include <crtdbg.h>
  15. #endif
  16.  
  17. //  Class to implement a DMO
  18. //
  19. //
  20. //       Assumes the number of input and output streams is fixed
  21. //       (these are template parameters)
  22. //
  23. //       Provides following services:
  24. //
  25. //          Basic parameter checking and locking
  26. //          Fully implements :
  27. //                 GetStreamCount
  28. //                 SetInputType
  29. //                 SetOutputType
  30. //                 GetCurrentInputType
  31. //                 GetCurrentOutputType
  32. //
  33. //          Checks if all types are set before streaming
  34. //          Automatically calls AllocateStreamingResources before streaming
  35. //              if it's not been called already
  36. //          Prevents streaming until the types on all non-optional streams
  37. //              have been set
  38. //
  39. //
  40. //  Derived class implements the following methods :
  41. //
  42. /*
  43.    HRESULT InternalGetInputStreamInfo(DWORD dwInputStreamIndex, DWORD *pdwFlags);
  44.    HRESULT InternalGetOutputStreamInfo(DWORD dwOutputStreamIndex, DWORD *pdwFlags);
  45.    HRESULT InternalCheckInputType(DWORD dwInputStreamIndex, const DMO_MEDIA_TYPE *pmt);
  46.    HRESULT InternalCheckOutputType(DWORD dwOutputStreamIndex, const DMO_MEDIA_TYPE *pmt);
  47.    HRESULT InternalGetInputType(DWORD dwInputStreamIndex, DWORD dwTypeIndex,
  48.                             DMO_MEDIA_TYPE *pmt);
  49.    HRESULT InternalGetOutputType(DWORD dwOutputStreamIndex, DWORD dwTypeIndex,
  50.                             DMO_MEDIA_TYPE *pmt);
  51.    HRESULT InternalGetInputSizeInfo(DWORD dwInputStreamIndex, DWORD *pcbSize,
  52.                             DWORD *pcbMaxLookahead, DWORD *pcbAlignment);
  53.    HRESULT InternalGetOutputSizeInfo(DWORD dwOutputStreamIndex, DWORD *pcbSize,
  54.                              DWORD *pcbAlignment);
  55.    HRESULT InternalGetInputMaxLatency(DWORD dwInputStreamIndex, REFERENCE_TIME *prtMaxLatency);
  56.    HRESULT InternalSetInputMaxLatency(DWORD dwInputStreamIndex, REFERENCE_TIME rtMaxLatency);
  57.    HRESULT InternalFlush();
  58.    HRESULT InternalDiscontinuity(DWORD dwInputStreamIndex);
  59.    HRESULT InternalAllocateStreamingResources();
  60.    HRESULT InternalFreeStreamingResources();
  61.    HRESULT InternalProcessInput(DWORD dwInputStreamIndex, IMediaBuffer *pBuffer,
  62.                                DWORD dwFlags, REFERENCE_TIME rtTimestamp,
  63.                                REFERENCE_TIME rtTimelength);
  64.    HRESULT InternalProcessOutput(DWORD dwFlags, DWORD cOutputBufferCount,
  65.                                DMO_OUTPUT_DATA_BUFFER *pOutputBuffers,
  66.                            DWORD *pdwStatus);
  67.    HRESULT InternalAcceptingInput(DWORD dwInputStreamIndex);
  68.    void Lock();
  69.    void Unlock();
  70.  
  71.    Notes:
  72.        The derived class is meant to do most work to initialize streaming
  73.        in AllocateStreamingResources rather than when types are set.
  74.  
  75.        This centralizes the work to one
  76.        clear place based on the types set for all streams.
  77.  
  78.        The derived class implements locking.
  79.  
  80.        The derived class implements the IUnknown methods
  81.  
  82.    Usage example (1 input and 1 output) :
  83.    class CMyDMO : public IMediaObjectImpl<CMyDmo, 1, 1>,
  84.                   ...
  85. */
  86.  
  87.  
  88. #define INTERNAL_CALL(_T_, _X_) \
  89.     static_cast<_T_ *>(this)->Internal##_X_
  90.  
  91. template <class _DERIVED_, int NUMBEROFINPUTS, int NUMBEROFOUTPUTS>
  92. class IMediaObjectImpl : public IMediaObject
  93. {
  94. private:
  95.     // Member variables
  96.     struct {
  97.         DWORD   fTypeSet:1;
  98.         DWORD   fIncomplete:1;
  99.         DMO_MEDIA_TYPE CurrentMediaType;
  100.     } m_InputInfo[NUMBEROFINPUTS], m_OutputInfo[NUMBEROFOUTPUTS];
  101.  
  102.     bool m_fTypesSet;
  103.     bool m_fFlushed;
  104.     bool m_fResourcesAllocated;
  105.  
  106. protected:
  107.  
  108.     //  Helpers
  109.     bool InputTypeSet(DWORD ulInputStreamIndex) const
  110.     {
  111.         _ASSERTE(ulInputStreamIndex < NUMBEROFINPUTS);
  112.         return 0 != m_InputInfo[ulInputStreamIndex].fTypeSet;
  113.     }
  114.  
  115.     bool OutputTypeSet(DWORD ulOutputStreamIndex) const
  116.     {
  117.         _ASSERTE(ulOutputStreamIndex < NUMBEROFOUTPUTS);
  118.         return 0 != m_OutputInfo[ulOutputStreamIndex].fTypeSet;
  119.     }
  120.     const DMO_MEDIA_TYPE *InputType(DWORD ulInputStreamIndex)
  121.     {
  122.         if (!InputTypeSet(ulInputStreamIndex)) {
  123.             return NULL;
  124.         }
  125.         return &m_InputInfo[ulInputStreamIndex].CurrentMediaType;
  126.     }
  127.     const DMO_MEDIA_TYPE *OutputType(DWORD ulOutputStreamIndex)
  128.     {
  129.         if (!OutputTypeSet(ulOutputStreamIndex)) {
  130.             return NULL;
  131.         }
  132.         return &m_OutputInfo[ulOutputStreamIndex].CurrentMediaType;
  133.     }
  134.  
  135.  
  136.     class LockIt
  137.     {
  138.     public:
  139.         LockIt(_DERIVED_ *p) : m_p(p)
  140.         {
  141.             static_cast<_DERIVED_ *>(m_p)->Lock();
  142.         }
  143.         ~LockIt()
  144.         {
  145.             static_cast<_DERIVED_ *>(m_p)->Unlock();
  146.         }
  147.         _DERIVED_ *const m_p;
  148.     };
  149.  
  150.     bool CheckTypesSet()
  151.     {
  152.         m_fTypesSet = false;
  153.         DWORD dw;
  154.         for (dw = 0; dw < NUMBEROFINPUTS; dw++) {
  155.             if (!InputTypeSet(dw)) {
  156.                 return false;
  157.             }
  158.         }
  159.         for (dw = 0; dw < NUMBEROFOUTPUTS; dw++) {
  160.             if (!OutputTypeSet(dw)) {
  161.                 //  Check if it's optional
  162.                 DWORD dwFlags;
  163. #ifdef _DEBUG
  164.                 dwFlags = 0xFFFFFFFF;
  165. #endif
  166.                 INTERNAL_CALL(_DERIVED_, GetOutputStreamInfo)(dw, &dwFlags);
  167.                 _ASSERTE(0 == (dwFlags & ~(DMO_OUTPUT_STREAMF_WHOLE_SAMPLES |
  168.                                          DMO_OUTPUT_STREAMF_SINGLE_SAMPLE_PER_BUFFER |
  169.                                          DMO_OUTPUT_STREAMF_FIXED_SAMPLE_SIZE |
  170.                                          DMO_OUTPUT_STREAMF_DISCARDABLE |
  171.                                          DMO_OUTPUT_STREAMF_OPTIONAL)));
  172.                 if (!(dwFlags & DMO_OUTPUT_STREAMF_OPTIONAL)) {
  173.                     return false;
  174.                 }
  175.             }
  176.         }
  177.         m_fTypesSet = true;
  178.         return true;
  179.     }
  180.  
  181.  
  182.     IMediaObjectImpl() :
  183.         m_fTypesSet(false),
  184.         m_fFlushed(true),
  185.         m_fResourcesAllocated(false)
  186.     {
  187.         ZeroMemory(&m_InputInfo, sizeof(m_InputInfo));
  188.         ZeroMemory(&m_OutputInfo, sizeof(m_OutputInfo));
  189.     }
  190.  
  191.     virtual ~IMediaObjectImpl() {
  192.         DWORD dwCurrentType;
  193.  
  194.         for (dwCurrentType = 0; dwCurrentType < NUMBEROFINPUTS; dwCurrentType++) {
  195.             if(InputTypeSet(dwCurrentType)) {
  196.                 MoFreeMediaType(&m_InputInfo[dwCurrentType].CurrentMediaType);
  197.             }
  198.         }
  199.  
  200.         for (dwCurrentType = 0; dwCurrentType < NUMBEROFOUTPUTS; dwCurrentType++) {
  201.             if(OutputTypeSet(dwCurrentType)) {
  202.                 MoFreeMediaType(&m_OutputInfo[dwCurrentType].CurrentMediaType);
  203.             }
  204.         }
  205.     }
  206.  
  207.  
  208.     // IMediaObject methods
  209.  
  210.  
  211.     //
  212.     // IMediaObject methods
  213.     //
  214.     STDMETHODIMP GetStreamCount(unsigned long *pulNumberOfInputStreams, unsigned long *pulNumberOfOutputStreams)
  215.     {
  216.         LockIt lck(static_cast<_DERIVED_ *>(this));
  217.         if (pulNumberOfInputStreams == NULL ||
  218.             pulNumberOfOutputStreams == NULL) {
  219.             return E_POINTER;
  220.         }
  221.         *pulNumberOfInputStreams  = NUMBEROFINPUTS;
  222.         *pulNumberOfOutputStreams = NUMBEROFOUTPUTS;
  223.         return S_OK;
  224.     }
  225.  
  226.     STDMETHODIMP GetInputStreamInfo(ULONG ulStreamIndex, DWORD *pdwFlags)
  227.     {
  228.         LockIt lck(static_cast<_DERIVED_ *>(this));
  229.         if (ulStreamIndex >= NUMBEROFINPUTS) {
  230.             return DMO_E_INVALIDSTREAMINDEX;
  231.         }
  232.         if (pdwFlags == NULL) {
  233.             return E_POINTER;
  234.         }
  235.         HRESULT hr = INTERNAL_CALL(_DERIVED_, GetInputStreamInfo)(ulStreamIndex, pdwFlags);
  236.         _ASSERTE(0 == (*pdwFlags & ~(DMO_INPUT_STREAMF_WHOLE_SAMPLES |
  237.                                    DMO_INPUT_STREAMF_SINGLE_SAMPLE_PER_BUFFER |
  238.                                    DMO_INPUT_STREAMF_FIXED_SAMPLE_SIZE |
  239.                                    DMO_INPUT_STREAMF_HOLDS_BUFFERS)));
  240.         return hr;
  241.     }
  242.  
  243.     STDMETHODIMP GetOutputStreamInfo(ULONG ulStreamIndex, DWORD *pdwFlags)
  244.     {
  245.         LockIt lck(static_cast<_DERIVED_ *>(this));
  246.         if (ulStreamIndex >= NUMBEROFOUTPUTS) {
  247.             return DMO_E_INVALIDSTREAMINDEX;
  248.         }
  249.         if (pdwFlags == NULL) {
  250.             return E_POINTER;
  251.         }
  252.         HRESULT hr = INTERNAL_CALL(_DERIVED_, GetOutputStreamInfo)(ulStreamIndex, pdwFlags);
  253.         _ASSERTE(0 == (*pdwFlags & ~(DMO_OUTPUT_STREAMF_WHOLE_SAMPLES |
  254.                                    DMO_OUTPUT_STREAMF_SINGLE_SAMPLE_PER_BUFFER |
  255.                                    DMO_OUTPUT_STREAMF_FIXED_SAMPLE_SIZE |
  256.                                    DMO_OUTPUT_STREAMF_DISCARDABLE |
  257.                                    DMO_OUTPUT_STREAMF_OPTIONAL)));
  258.         return hr;
  259.     }
  260.  
  261.     STDMETHODIMP GetInputType(ULONG ulStreamIndex, ULONG ulTypeIndex, DMO_MEDIA_TYPE *pmt) {
  262.         if (ulStreamIndex >= NUMBEROFINPUTS) {
  263.             return DMO_E_INVALIDSTREAMINDEX;
  264.         }
  265.         LockIt lck(static_cast<_DERIVED_ *>(this));
  266.         return INTERNAL_CALL(_DERIVED_, GetInputType)(ulStreamIndex, ulTypeIndex, pmt);
  267.     }
  268.  
  269.     STDMETHODIMP GetOutputType(ULONG ulStreamIndex, ULONG ulTypeIndex, DMO_MEDIA_TYPE *pmt) {
  270.         if (ulStreamIndex >= NUMBEROFOUTPUTS) {
  271.             return DMO_E_INVALIDSTREAMINDEX;
  272.         }
  273.         LockIt lck(static_cast<_DERIVED_ *>(this));
  274.         return INTERNAL_CALL(_DERIVED_, GetOutputType)(ulStreamIndex, ulTypeIndex, pmt);
  275.     }
  276.  
  277.     STDMETHODIMP GetInputCurrentType(ULONG ulStreamIndex, DMO_MEDIA_TYPE *pmt) {
  278.         if (ulStreamIndex >= NUMBEROFINPUTS) {
  279.             return DMO_E_INVALIDSTREAMINDEX;
  280.         }
  281.         if (NULL == pmt) {
  282.             return E_POINTER;
  283.         }
  284.         LockIt lck(static_cast<_DERIVED_ *>(this));
  285.         if (InputTypeSet(ulStreamIndex))
  286.             return MoCopyMediaType(pmt,
  287.                                    &m_InputInfo[ulStreamIndex].CurrentMediaType);
  288.         else
  289.            return DMO_E_TYPE_NOT_SET;
  290.     }
  291.  
  292.     STDMETHODIMP GetOutputCurrentType(ULONG ulStreamIndex, DMO_MEDIA_TYPE *pmt) {
  293.         if (ulStreamIndex >= NUMBEROFOUTPUTS) {
  294.             return DMO_E_INVALIDSTREAMINDEX;
  295.         }
  296.         if (NULL == pmt) {
  297.             return E_POINTER;
  298.         }
  299.         LockIt lck(static_cast<_DERIVED_ *>(this));
  300.         if (OutputTypeSet(ulStreamIndex))
  301.             return MoCopyMediaType(pmt,
  302.                                    &m_OutputInfo[ulStreamIndex].CurrentMediaType);
  303.         else
  304.            return DMO_E_TYPE_NOT_SET;
  305.     }
  306.  
  307.     STDMETHODIMP GetInputSizeInfo(ULONG ulStreamIndex, ULONG *pulSize, ULONG *pcbMaxLookahead, ULONG *pulAlignment) {
  308.         if (ulStreamIndex >= NUMBEROFINPUTS) {
  309.             return DMO_E_INVALIDSTREAMINDEX;
  310.         }
  311.         if (NULL == pulSize || NULL == pulAlignment ||
  312.             NULL == pcbMaxLookahead) {
  313.             return E_POINTER;
  314.         }
  315.         LockIt lck(static_cast<_DERIVED_ *>(this));
  316.         if (!InputTypeSet(ulStreamIndex)) {
  317.            return DMO_E_TYPE_NOT_SET;
  318.         }
  319.         return INTERNAL_CALL(_DERIVED_, GetInputSizeInfo)(ulStreamIndex, pulSize, pcbMaxLookahead, pulAlignment);
  320.     }
  321.  
  322.     STDMETHODIMP GetOutputSizeInfo(ULONG ulStreamIndex, ULONG *pulSize, ULONG *pulAlignment) {
  323.         if (ulStreamIndex >= NUMBEROFOUTPUTS) {
  324.             return DMO_E_INVALIDSTREAMINDEX;
  325.         }
  326.         if (NULL == pulSize || NULL == pulAlignment) {
  327.             return E_POINTER;
  328.         }
  329.         LockIt lck(static_cast<_DERIVED_ *>(this));
  330.         if (!m_fTypesSet || !OutputTypeSet(ulStreamIndex)) {
  331.            return DMO_E_TYPE_NOT_SET;
  332.         }
  333.         return INTERNAL_CALL(_DERIVED_, GetOutputSizeInfo)(ulStreamIndex, pulSize, pulAlignment);
  334.     }
  335.  
  336.     STDMETHODIMP SetInputType(ULONG ulStreamIndex, const DMO_MEDIA_TYPE *pmt, DWORD dwFlags) {
  337.         if (ulStreamIndex >= NUMBEROFINPUTS) {
  338.             return DMO_E_INVALIDSTREAMINDEX;
  339.         }
  340.         if (dwFlags & ~ (DMO_SET_TYPEF_CLEAR | DMO_SET_TYPEF_TEST_ONLY)) {
  341.             return E_INVALIDARG;
  342.         }
  343.  
  344.         LockIt lck(static_cast<_DERIVED_ *>(this));
  345.  
  346.         if (dwFlags & DMO_SET_TYPEF_CLEAR) {
  347.             MoFreeMediaType(&m_InputInfo[ulStreamIndex].CurrentMediaType);
  348.             m_InputInfo[ulStreamIndex].fTypeSet = FALSE;
  349.             if (!CheckTypesSet()) {
  350.                 Flush();
  351.                 FreeStreamingResources();
  352.             }
  353.             return NOERROR;
  354.         }
  355.         if (NULL == pmt) {
  356.             return E_POINTER;
  357.         }
  358.         HRESULT hr = INTERNAL_CALL(_DERIVED_, CheckInputType)(ulStreamIndex, pmt);
  359.         if (FAILED(hr))
  360.            return hr;
  361.  
  362.         if (dwFlags & DMO_SET_TYPEF_TEST_ONLY) {
  363.            return NOERROR;
  364.         }
  365.  
  366.  
  367.         // actually set the type
  368.         DMO_MEDIA_TYPE mtTemp;
  369.         if (S_OK == MoCopyMediaType(&mtTemp, pmt)) {
  370.             // Free any previous mediatype
  371.             if (InputTypeSet(ulStreamIndex)) {
  372.                 MoFreeMediaType(&m_InputInfo[ulStreamIndex].CurrentMediaType);
  373.             }
  374.             m_InputInfo[ulStreamIndex].CurrentMediaType = mtTemp;
  375.             m_InputInfo[ulStreamIndex].fTypeSet = TRUE;
  376.             CheckTypesSet();
  377.         } else {
  378.             return E_OUTOFMEMORY;
  379.         }
  380.  
  381.         return NOERROR;
  382.     }
  383.  
  384.     STDMETHODIMP SetOutputType(ULONG ulStreamIndex, const DMO_MEDIA_TYPE *pmt, DWORD dwFlags) {
  385.         if (ulStreamIndex >= NUMBEROFOUTPUTS) {
  386.             return DMO_E_INVALIDSTREAMINDEX;
  387.         }
  388.         if (dwFlags & ~ (DMO_SET_TYPEF_CLEAR | DMO_SET_TYPEF_TEST_ONLY)) {
  389.             return E_INVALIDARG;
  390.         }
  391.  
  392.         LockIt lck(static_cast<_DERIVED_ *>(this));
  393.  
  394.         if (dwFlags & DMO_SET_TYPEF_CLEAR) {
  395.             MoFreeMediaType(&m_OutputInfo[ulStreamIndex].CurrentMediaType);
  396.             m_OutputInfo[ulStreamIndex].fTypeSet = FALSE;
  397.             if (!CheckTypesSet()) {
  398.                 Flush();
  399.                 FreeStreamingResources();
  400.             }
  401.             return NOERROR;
  402.         }
  403.         if (NULL == pmt) {
  404.             return E_POINTER;
  405.         }
  406.         HRESULT hr = INTERNAL_CALL(_DERIVED_, CheckOutputType)(ulStreamIndex, pmt);
  407.         if (FAILED(hr)) {
  408.            return hr;
  409.         }
  410.  
  411.         if (dwFlags & DMO_SET_TYPEF_TEST_ONLY) {
  412.            return NOERROR;
  413.         }
  414.  
  415.  
  416.         // actually set the type
  417.         DMO_MEDIA_TYPE mtTemp;
  418.         if (S_OK == MoCopyMediaType(&mtTemp, pmt)) {
  419.             // Free any previous mediatype
  420.             if (OutputTypeSet(ulStreamIndex)) {
  421.                 MoFreeMediaType(&m_OutputInfo[ulStreamIndex].CurrentMediaType);
  422.             }
  423.             m_OutputInfo[ulStreamIndex].CurrentMediaType = mtTemp;
  424.             m_OutputInfo[ulStreamIndex].fTypeSet = TRUE;
  425.             CheckTypesSet();
  426.         } else {
  427.             return E_OUTOFMEMORY;
  428.         }
  429.  
  430.         return NOERROR;
  431.     }
  432.  
  433.     STDMETHODIMP GetInputStatus(
  434.         ULONG ulStreamIndex,
  435.         DWORD *pdwStatus
  436.     ) {
  437.         if (ulStreamIndex >= NUMBEROFINPUTS) {
  438.             return DMO_E_INVALIDSTREAMINDEX;
  439.         }
  440.         if (NULL == pdwStatus) {
  441.             return E_POINTER;
  442.         }
  443.         *pdwStatus = 0;
  444.  
  445.         LockIt lck(static_cast<_DERIVED_ *>(this));
  446.  
  447.         if (!m_fTypesSet) {
  448.             return DMO_E_TYPE_NOT_SET;
  449.         }
  450.  
  451.         if (INTERNAL_CALL(_DERIVED_, AcceptingInput)(ulStreamIndex) == S_OK) {
  452.            *pdwStatus |= DMO_INPUT_STATUSF_ACCEPT_DATA;
  453.         }
  454.         return NOERROR;
  455.     }
  456.  
  457.     STDMETHODIMP GetInputMaxLatency(unsigned long ulStreamIndex, REFERENCE_TIME *prtLatency) {
  458.  
  459.         if (prtLatency == NULL) {
  460.             return E_POINTER;
  461.         }
  462.         if (ulStreamIndex >= NUMBEROFINPUTS) {
  463.             return DMO_E_INVALIDSTREAMINDEX;
  464.         }
  465.  
  466.         LockIt lck(static_cast<_DERIVED_ *>(this));
  467.  
  468.         return INTERNAL_CALL(_DERIVED_, GetInputMaxLatency)(ulStreamIndex, prtLatency);
  469.     }
  470.  
  471.     STDMETHODIMP SetInputMaxLatency(unsigned long ulStreamIndex, REFERENCE_TIME rtLatency) {
  472.         if (ulStreamIndex >= NUMBEROFINPUTS) {
  473.             return DMO_E_INVALIDSTREAMINDEX;
  474.         }
  475.  
  476.         LockIt lck(static_cast<_DERIVED_ *>(this));
  477.  
  478.         return INTERNAL_CALL(_DERIVED_, SetInputMaxLatency)(ulStreamIndex, rtLatency);
  479.     }
  480.  
  481.     STDMETHODIMP Discontinuity(ULONG ulStreamIndex) {
  482.         if (ulStreamIndex >= NUMBEROFINPUTS) {
  483.             return DMO_E_INVALIDSTREAMINDEX;
  484.         }
  485.  
  486.         LockIt lck(static_cast<_DERIVED_ *>(this));
  487.  
  488.         if (!m_fTypesSet) {
  489.             return DMO_E_TYPE_NOT_SET;
  490.         }
  491.  
  492.         if (S_OK != INTERNAL_CALL(_DERIVED_, AcceptingInput)(ulStreamIndex)) {
  493.             return DMO_E_NOTACCEPTING;
  494.         }
  495.  
  496.         return INTERNAL_CALL(_DERIVED_, Discontinuity)(ulStreamIndex);
  497.     }
  498.  
  499.     STDMETHODIMP Flush()
  500.     {
  501.         LockIt lck(static_cast<_DERIVED_ *>(this));
  502.  
  503.         if (!m_fTypesSet) {
  504.             return S_OK;
  505.         }
  506.         if (m_fFlushed) {
  507.             return S_OK;
  508.         }
  509.         HRESULT hr =  INTERNAL_CALL(_DERIVED_, Flush)();
  510.         m_fFlushed = true;
  511.         return hr;
  512.     }
  513.  
  514.     STDMETHODIMP AllocateStreamingResources() {
  515.         LockIt lck(static_cast<_DERIVED_ *>(this));
  516.         if (!m_fTypesSet) {
  517.             return DMO_E_TYPE_NOT_SET;
  518.         }
  519.         if (m_fResourcesAllocated) {
  520.             return S_OK;
  521.         }
  522.         HRESULT hr = INTERNAL_CALL(_DERIVED_, AllocateStreamingResources)();
  523.         if (SUCCEEDED(hr)) {
  524.             m_fResourcesAllocated = true;
  525.         }
  526.         return hr;
  527.     }
  528.  
  529.     STDMETHODIMP FreeStreamingResources()
  530.     {
  531.         LockIt lck(static_cast<_DERIVED_ *>(this));
  532.         if (m_fResourcesAllocated) {
  533.             m_fResourcesAllocated = false;
  534.             INTERNAL_CALL(_DERIVED_, Flush)();
  535.             return INTERNAL_CALL(_DERIVED_, FreeStreamingResources)();
  536.         }
  537.         return S_OK;
  538.     }
  539.  
  540.     //
  541.     // Processing methods - public entry points
  542.     //
  543.     STDMETHODIMP ProcessInput(
  544.         DWORD ulStreamIndex,
  545.         IMediaBuffer *pBuffer, // [in], must not be NULL
  546.         DWORD dwFlags, // [in] - discontinuity, timestamp, etc.
  547.         REFERENCE_TIME rtTimestamp, // [in], valid if flag set
  548.         REFERENCE_TIME rtTimelength // [in], valid if flag set
  549.     ) {
  550.         if (!pBuffer) {
  551.             return E_POINTER;
  552.         }
  553.         if (ulStreamIndex >= NUMBEROFINPUTS) {
  554.             return DMO_E_INVALIDSTREAMINDEX;
  555.         }
  556.         if (dwFlags & ~(DMO_INPUT_DATA_BUFFERF_SYNCPOINT |
  557.                         DMO_INPUT_DATA_BUFFERF_TIME |
  558.                         DMO_INPUT_DATA_BUFFERF_TIMELENGTH)) {
  559.             return E_INVALIDARG;
  560.         }
  561.  
  562.         LockIt lck(static_cast<_DERIVED_ *>(this));
  563.  
  564.         //  Make sure all streams have media types set and resources are allocated
  565.         HRESULT hr = AllocateStreamingResources();
  566.         if (FAILED(hr)) {
  567.             return hr;
  568.         }
  569.         if (INTERNAL_CALL(_DERIVED_, AcceptingInput)(ulStreamIndex) != S_OK) {
  570.             return DMO_E_NOTACCEPTING;
  571.         }
  572.  
  573.         m_fFlushed = false;
  574.  
  575.         return INTERNAL_CALL(_DERIVED_, ProcessInput)(
  576.                                     ulStreamIndex,
  577.                                     pBuffer,
  578.                                     dwFlags,
  579.                                     rtTimestamp,
  580.                                     rtTimelength);
  581.     }
  582.  
  583.     STDMETHODIMP ProcessOutput(
  584.                     DWORD dwFlags,
  585.                     DWORD ulOutputBufferCount,
  586.                     DMO_OUTPUT_DATA_BUFFER *pOutputBuffers,
  587.                     DWORD *pdwStatus)
  588.     {
  589.         if (pdwStatus == NULL) {
  590.             return E_POINTER;
  591.         }
  592.  
  593.  
  594.         if (ulOutputBufferCount != NUMBEROFOUTPUTS || (dwFlags & ~DMO_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER)) {
  595.            return E_INVALIDARG;
  596.         }
  597.  
  598.         if (NUMBEROFOUTPUTS != 0 && pOutputBuffers == NULL) {
  599.             return E_POINTER;
  600.         }
  601.  
  602.         *pdwStatus = 0;
  603.  
  604.         LockIt lck(static_cast<_DERIVED_ *>(this));
  605.  
  606.         HRESULT hr = AllocateStreamingResources();
  607.         if (FAILED(hr)) {
  608.             return hr;
  609.         }
  610.  
  611.         for (DWORD dw = 0; dw < NUMBEROFOUTPUTS; dw++) {
  612.             pOutputBuffers[dw].dwStatus = 0;
  613.         }
  614.  
  615.         hr = INTERNAL_CALL(_DERIVED_, ProcessOutput)(
  616.                            dwFlags,
  617.                            ulOutputBufferCount,
  618.                            pOutputBuffers,
  619.                            pdwStatus);
  620.  
  621.         // remember the DMO's incomplete status
  622.         for (dw = 0; dw < NUMBEROFOUTPUTS; dw++) {
  623.             if (pOutputBuffers[dw].dwStatus & DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE) {
  624.                 m_OutputInfo[dw].fIncomplete = TRUE;
  625.             } else {
  626.                 m_OutputInfo[dw].fIncomplete = FALSE;
  627.             }
  628.         }
  629.  
  630.         return hr;
  631.     }
  632.  
  633.     STDMETHODIMP DMOLock(LONG lLock)
  634.     {
  635.         if (lLock) {
  636.             static_cast<_DERIVED_ *>(this)->Lock();
  637.         } else {
  638.             static_cast<_DERIVED_ *>(this)->Unlock();
  639.         }
  640.         return S_OK;
  641.     }
  642. };
  643.  
  644. #endif // _dmoimpl_h_
  645.  
  646.